package mutation;



import instrumentation.BlockClass;
import instrumentation.TrackerCoverage;

import java.io.IOException;
import java.util.Calendar;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import executor.ReflectionExecutor;
import ga.GAInfo;
import ga.Individual;
import mdr.MethodDependences;
import mdr.RecommendGenerator;
import model.CUT;
import model.Filter;
import model.TestClusterBuilder;

import operations.Operation;
import util.GAConfig;
import util.GAOperationsConfig;
import ReadWGZ.ReadFilewgzMDR;

public class TestMutationMain {
	public static void main(String[] args) throws IOException,
	ClassNotFoundException{
		long startTime = Calendar.getInstance().getTimeInMillis();

		Mutation ChangeValueStrategy = GAOperationsConfig.getMutationChangeValueStrategy();
		Mutation DeleteStatmentStrategy = GAOperationsConfig.getMutationMethodDeleteStrategy();
		Mutation InsertStatmentStrategy = GAOperationsConfig.getMutationMethodInsertStrategy();
		ReadFilewgzMDR readFileWGZ = new ReadFilewgzMDR();
		 TrackerCoverage tracker=  TrackerCoverage.getTracker();
		GAInfo gaInfo=  new GAInfo();
		gaInfo.setTracker(tracker);
		gaInfo.setTestTimeOut( 60 * 10000); ;
		gaInfo.setStartTime(startTime);
			 Set<Class<?>> allClasses = new LinkedHashSet<Class<?>>();
		      //get class from file
		      allClasses.addAll(TestClusterBuilder.readClassFromFile());

		      System.out.println("There are " + allClasses.size() + " classes as input");
		      
		      
		      System.out.println(allClasses);

		      List<TestClusterBuilder> TestClusterList= TestClusterBuilder.buildTestClusterList(allClasses);
				 Map<String, BlockClass> blockClasses=readFileWGZ.readFileWGZ(TestClusterList);
				 Map<String,Set<Integer>> classBranches=readFileWGZ.getClazzCondition(blockClasses);

				gaInfo.setMapBlockClasses(blockClasses);
				gaInfo.setClazzBranches(classBranches);

		      for(TestClusterBuilder tCluster:TestClusterList){
					//the method recommender
					 if(GAConfig.UseReadWrietRelation){
						 System.out.println( "Building up method dependence model for diversifying...");
						 Set<Class<?>> cluster = new LinkedHashSet<Class<?>>();
							for(String cName:tCluster.getCluster().keySet()){
								Class<?> cls=tCluster.getCluster().get(cName).getClazz();
								if(Filter.isPrimitiveOrStringType(cls))continue;
								if(cls.getName().startsWith("java.")) continue;
								if(cls.getName().startsWith("sun.")) continue;
								if(cls.getName().contains("$")) continue;
								if(!Filter.canUse(cls))continue;
								cluster.add(cls);
							}
							gaInfo.setTestCluster(tCluster);
							MethodDependences recommender = new MethodDependences(cluster);
							 recommender.buildDependence(tCluster.getStatements());
							 System.out.println("Finishing method dependence model building");
							 gaInfo.setMethodRelations(recommender);
							 
							 ////print out the relation methods dependency
								Set<Class<?>> classToTest= new LinkedHashSet<Class<?>>();

								for(Class<?> cls: tCluster.getClassToTest().values())
									classToTest.add(cls);
							System.out.println("--------------------");
							System.out.println("     CUT: "+ classToTest);
							System.out.println("--------------------");
							System.out.println(recommender.showDependence(classToTest));
							System.out.println(recommender.showStatmentsWriteFileds(classToTest));
							RecommendGenerator recommendGenerator=new  RecommendGenerator(gaInfo);
							 gaInfo.setRecommendGenerator(recommendGenerator);
							 System.out.println(recommendGenerator.toString());
					 }
					CUT cut = tCluster.getCut();
					
					Map<String, Class<?>> classesToTest = tCluster.getClassToTest();
					
					String clz = classesToTest.keySet().iterator().next();
					System.out.println("Class " + clz + " is being Tested");

				  gaInfo.setClzToTest(cut.getClazz());
		    	  gaInfo.setTestCluster(tCluster);
		    	  ChangeValueStrategy.setExtraInfo(gaInfo);
		    	  DeleteStatmentStrategy.setExtraInfo(gaInfo);
		    	  InsertStatmentStrategy.setExtraInfo(gaInfo);
			      List<Operation> ops=new LinkedList<Operation>();

			      List<Operation> initialConstructors= Operation.randomGenerateInitialConstructors(tCluster);
			      ops.addAll(Operation.randomlyGenerateOperation(tCluster,10));
			      Individual individual=new Individual(initialConstructors,ops);
				 
			      ReflectionExecutor.execute(gaInfo,individual);
			      tracker.calculateFitness(individual,gaInfo.getClazzBranches(clz));
			      
			      System.out.println("Original individual: \n" + individual);
			      System.out.println(tracker.toString());
			      Individual individual2=null;
					int choice=3;
	      
			      if(choice==1){
			    	  System.out.println("Input value changed.");
			    	   individual2=ChangeValueStrategy.mutateIndividual(individual);
			      }
			      if(choice==2){
			    	   individual2=DeleteStatmentStrategy.mutateIndividual(individual);
			    	   System.out.println("Delete Methods.");
						System.out.println("Mutated individual: \n" + individual2);
		    	   
		      }
			      if(choice==3){
			    	  System.out.println("Insert Methods.");
			    	   individual2=InsertStatmentStrategy.mutateIndividual(individual);
			      }
			      
			      System.out.println("size-1 vs size-2 : \n" + individual.getSize() + " vs  "+individual2.getSize() );
//					System.out.println("Original individual: \n" + individual);
					System.out.println("Mutated individual: \n" + individual2);
			      ReflectionExecutor.execute(gaInfo,individual2);
					System.out.println("Mutated individual: \n" + individual2);

  				  System.out.println(tracker.toString());

		      }
//			ChangeValueStrategy.setExtraInfo(gaInfo);
//			
//			System.out.println("Original individual: \n" + individual1);
//
//			System.out.println("Mutated individual: \n" + individual2);
		   
			System.exit(0);

	}

}
